/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.disparity;

import java.util.*;
import org.apache.commons.lang3.ArrayUtils;

/**
 *
 * @author aboulton
 */
public class CompareFiles {

    public static Map<Integer, Byte[]> diffs = new TreeMap<>();
    private static List<Byte> tempData = new ArrayList<>();

    public static Map<Integer, Byte[]> compare(byte[] originalFile, byte[] patchedFile) {
        boolean isDifferent = false;

        if (originalFile.length == patchedFile.length) {
            for (int idx = 0; idx < patchedFile.length; idx++) {

                if (originalFile[idx] != patchedFile[idx]) {
                    isDifferent = true;

                    tempData.add(patchedFile[idx]);
                } else //the difference stopped
                {
                    if (isDifferent) {
                        isDifferent = recordChanges(idx);
                    }
                }
            }

            return diffs;

        }

        if (originalFile.length > patchedFile.length) {
            for (int idx = 0; idx < patchedFile.length; idx++) {

                if (originalFile[idx] != patchedFile[idx]) {
                    isDifferent = true;
                    //         System.out.println("Offset: " + idx);
                    //       System.out.println(fileTwo[idx]);
                    tempData.add(patchedFile[idx]);
                } else //the difference stopped
                {
                    if (isDifferent) {
                        isDifferent = recordChanges(idx);
                    }
                }
            }

            if (isDifferent) {
                int firstOffsetOfChange = patchedFile.length - tempData.size();

                Byte[] data = new Byte[tempData.size()];

                data = tempData.toArray(data);
                diffs.put(firstOffsetOfChange, data);
            }

            return diffs;
        }

        //This means for whatever reason the patch has caused the file to grow. It may not always be down to the patch, it could even be due to compression
        //for example if a JAR file was unpacked, then repacked with the modded class file it can result in what looks like a totally different JAR.
        if (originalFile.length < patchedFile.length) {

            //2. Get the rest of the differences
            int index = 0;
            for (int idx = 0; idx < originalFile.length; idx++, index = idx) {

                if (originalFile[idx] != patchedFile[idx]) //do the bytes differ between the files
                {

                    isDifferent = true;

                    tempData.add(patchedFile[idx]); //save the byte change
                } else //no longer any difference
                {
                    if (isDifferent) //when true, means we've captured some differed data
                    {
                        isDifferent = recordChanges(idx); 
                    }
                }
            }

            //Copy the rest of the patched file into the buffer

            if (isDifferent) {
                int firstOffsetOfChange = index - tempData.size();

                Byte[] data = new Byte[tempData.size()];

                data = tempData.toArray(data);
                diffs.put(firstOffsetOfChange, data);
            }

            //Now let's grab any data at the end of the patched file that wasn't present in the original
            byte[] appendedDataOnPatched = Arrays.copyOfRange(patchedFile, originalFile.length, patchedFile.length);
            diffs.put(originalFile.length, ArrayUtils.toObject(appendedDataOnPatched));

        }

        
        return diffs;
    }

    private static boolean recordChanges(int idx) {
        boolean isDifferent;
        int firstOffsetOfChange = idx - tempData.size(); //beginning offset when we started to notice the change
        Byte[] data = new Byte[tempData.size()];
        data = tempData.toArray(data);
        diffs.put(firstOffsetOfChange, data); //officially record the data changes
        tempData = new ArrayList<>();
        isDifferent = false; //get back to seeing if there are differences
        return isDifferent;
    }
}
